/* $RCSFile: CountryStoreResources.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/Country/CountryStoreResources.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:28  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.IO;
using System.Data;
using System.ComponentModel;
using System.Xml;
using System.Web;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Collections.Specialized;

using AddonNice.Diagnostics;
using AddonNice.Settings;
using AddonNice.Settings.Cache;

namespace AddonNice.Country
{
	/// <summary>
	/// An interface to compiled resources
	/// </summary>
    public class CountryStoreResources : ResourceManager
    {
        /// <summary>
        /// The assembly in which are located the current resources
        /// </summary>
        static Assembly _currentAssembly = null;
  		protected static Assembly CurrentAssembly
		{
			get
			{
                if (_currentAssembly == null)
                {
                    try
                    {
                        string path =   HttpRuntime.BinDirectory+"ADNCRM.dll";
                        if ( CountryTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CountryStoreResources CurrentAssembly LoadFrom  {0}.", path),CountryTraceSwitch.Sw.Info);
                        _currentAssembly = Assembly.LoadFrom(path);
                    }
                    catch (Exception ex)
                    {
                        if ( CountryTraceSwitch.Sw.TraceError )
                            System.Diagnostics.Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CountryStoreResources CurrentAssembly Assembly.LoadFrom failed ex: {0}.", ex),CountryTraceSwitch.Sw.Info);
                        throw;
                    }
                }
				return _currentAssembly;
			}
        }
        

        const string _storeCountryRegionsManager = "ADNCRM.Countries.xml";

        public CountryStoreResources() : base("ADNCRM.ISO31661", CurrentAssembly)
        {
    		if ( CountryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CountryStoreResources constructor called at {0}",DateTime.UtcNow),CountryTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Gets the list of supported cultures filtered by the specified CountryTypes.
        /// </summary>
        /// <returns></returns>
        public CountryInfo[] GetCountries(CountryTypes types)
        {
            string strKey   =   Key.GetCountries((int)types);
            if ( CurrentCache.Exists(strKey) )
                return (CountryInfo[] )CurrentCache.Get(strKey);
            Stream st       =   null;
            CountryInfo[] c =   null;
            try
            {
                st          =   CurrentAssembly.GetManifestResourceStream(_storeCountryRegionsManager);
                c           =   CountryInfoSerializer.Deserialize(st);
                // insert in cache for 2 hour
                if ( c.Length > 0 )
                    CurrentCache.InsertMinutes(strKey,c,1200);
            }
            catch (Exception ex)
            {
                if ( CountryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CountryStoreResources GetCountries  ex: {0}.", ex),CountryTraceSwitch.Sw.Info);
                throw;
            }
            finally
            {
                if (st != null)
                    st.Close();
            }
            return c;
        }

		/// <summary>
		/// Returns the value of the requested
		/// key in the neutral culture
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public virtual string GetValue(string key) 
		{
			return GetValue(key, CultureInfo.InvariantCulture);
		}

		/// <summary>
		/// Returns true if culture exists in current culture list
		/// </summary>
		/// <param name="culture"></param>
		/// <returns></returns>
		public virtual bool CultureExists(CultureInfo culture)
		{
			CultureInfo[] cultures = GetCultures();
			foreach (CultureInfo currentCulture in cultures)
			{
				if (currentCulture.Name == culture.Name)
					return true;
			}
			return false;
		}

		private CultureInfo[] innerCulturesCache = null;

		public virtual CultureInfo[] GetCultures()
		{
			if (innerCulturesCache == null) // it is readonly so we can cache it first time
			{
				ArrayList availableCultures = new ArrayList();

				CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);

				foreach (CultureInfo culture in cultures)
				{
					if (GetResourceSet(culture, false, false) != null)
						availableCultures.Add(culture);
				}
				innerCulturesCache = (CultureInfo[]) availableCultures.ToArray(typeof(CultureInfo));
			}
			return innerCulturesCache;
		}

		public string[] GetAllKeys(CultureInfo culture)
		{
            string strKey   =   Key.GetAllKeys(culture.LCID);
            if ( CurrentCache.Exists(strKey) )
                return (string[] )CurrentCache.Get(strKey);
			//Get culture
			string[] allKeys = GetAllKeys(CurrentAssembly.GetManifestResourceStream(GetResourceFileName(culture)));
			if (allKeys != null)
				return allKeys;

			//Resource fallback
			CultureInfo parent = culture.Parent;
			while (parent != null && parent != CultureInfo.InvariantCulture)
			{
				if (parent != null)
				{
					allKeys = GetAllKeys(CurrentAssembly.GetManifestResourceStream(GetResourceFileName(parent)));
					if (allKeys != null)
						return allKeys;
				}
				parent = parent.Parent;
			}

			//Return invariant
			allKeys = GetAllKeys(CurrentAssembly.GetManifestResourceStream(GetResourceFileName(CultureInfo.InvariantCulture)));
            if ( allKeys.Length > 0 )
               CurrentCache.InsertMinutes(strKey,allKeys,1200);
			return allKeys;
		}

		private string[] GetAllKeys(System.IO.Stream myResStream)
		{
			if (myResStream != null)
			{
				ArrayList allKeys           = new ArrayList();
				ResourceReader reader       = new ResourceReader(myResStream);
				IDictionaryEnumerator en    = reader.GetEnumerator();
				// Goes through the enumerator, getting the key and value pairs.
				while (en.MoveNext()) 
				{
					allKeys.Add(en.Key);
				}
				reader.Close();
				return (string[]) allKeys.ToArray(typeof(string));
			}
			return null;		
		}

		/// <summary>
		/// Internal data source
		/// </summary>
		/// <param name="key"></param>
		/// <param name="culture"></param>
		/// <returns></returns>
		public virtual string GetValue(string key, CultureInfo culture) 
		{
			string strText = null;
			try
			{
				strText = GetString(key, culture); //May fail: Cannot find resource
			}
			catch(ArgumentException)
			{}
			if ( string.IsNullOrEmpty(strText) || char.IsControl(strText, 0))
				strText = null; // was string.Empty
			return strText;
		}

    }
}